#region Copyright (c) 2006-2012 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2012 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion

using System;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using Widgetsphere.Generator.Common.GeneratorFramework;
using Widgetsphere.Generator.Common.Util;
using Widgetsphere.Generator.Forms;
using Widgetsphere.Generator.Models;

namespace Widgetsphere.Generator
{
	[GeneratorAttribute("{4B5CFCAF-C668-4d40-947C-83B2AAEBB2B5}", "Widgetsphere Model")]
	public class WidgetsphereGeneratorProject : IWidgetsphereGenerator, IXMLable
	{
		#region Constants
		//public const string ICSharpCodeFile = "ICSharpCode.SharpZipLib.dll";
		public const string CoreFile = "Widgetsphere.Core.dll";
		public const string EFCoreFile = "Widgetsphere.EFCore.dll";
		public const string MicrosoftServiceModelWeb = "Microsoft.ServiceModel.Web.dll";
		public const string CodeFirstCTP5 = "EntityFramework.dll";
		#endregion

		#region Member Variables

		private string _fileName = string.Empty;

		#endregion

		#region Constructors

		public WidgetsphereGeneratorProject()
		{
			var root = new ModelRoot(null);
			root.GeneratorProject = this;
			this.RootController = new ModelRootController(root);
		}

		#endregion

		#region Events

		public event Widgetsphere.Generator.Common.GeneratorFramework.VerifyDelegate VerifyComplete;
		protected void OnVerifyComplete(object sender, Widgetsphere.Generator.Common.EventArgs.MessageCollectionEventArgs e)
		{
			if (this.VerifyComplete != null)
				this.VerifyComplete(sender, e);
		}

		#endregion

		#region IXMLable Members

		public void XmlAppend(XmlNode node)
		{
			var oDoc = node.OwnerDocument;
			var ModelRootNode = oDoc.CreateElement("ModelRoot");
			RootController.Object.XmlAppend(ModelRootNode);
			node.AppendChild(ModelRootNode);
		}

		public void XmlLoad(XmlNode node)
		{
			var ModelRootNode = node.SelectSingleNode("ModelRoot");
			RootController.Object.XmlLoad(ModelRootNode);
			((ModelRoot)RootController.Object).CleanUp();
		}

		#endregion

		#region DomainProjectName

		public static string DomainProjectName(ModelRoot model)
		{
			var retval = model.CompanyName + "." + model.ProjectName;

			if (!string.IsNullOrEmpty(model.ModuleName))
				retval += "." + model.ModuleName;

			if (string.IsNullOrEmpty(model.DefaultNamespace))
				return retval;
			else
				return model.DefaultNamespace;
		}

		#endregion

		#region IWidgetsphereGeneratorProject

		public IModelObject Model
		{
			get { return RootController.Object; }
		}

		public IWidgetsphereModelObjectController RootController { get; set; }

		public ImageList ImageList
		{
			get { return ImageHelper.GetImageList(); }
		}

		public MenuCommand[] GetMenuCommands()
		{
			var menuVerify = new DefaultMenuCommand();
			menuVerify.Text = "Verify";
			menuVerify.Click += new EventHandler(menuVerify_Click);

			var menu1 = new DefaultMenuCommand();
			menu1.Text = "-";

			var menuImport = new DefaultMenuCommand();
			menuImport.Text = "Import Database";
			menuImport.Click += new EventHandler(menuImport_Click);

			return new MenuCommand[] { menuVerify, menu1, menuImport };
		}

		#endregion

		#region Menu Handlers

		private void menuImport_Click(object sender, System.EventArgs e)
		{
		}

		private void menuVerify_Click(object sender, System.EventArgs e)
		{
			var list = ((BaseModelObjectController)this.RootController).Verify();
			this.OnVerifyComplete(this, new Widgetsphere.Generator.Common.EventArgs.MessageCollectionEventArgs(list));
		}

		#endregion

		#region IGenerator Members

		public string FileName
		{
			get { return _fileName; }
			set { _fileName = value; }
		}

		public void HandleCommand(string command)
		{
			if (command == "ImportModel")
			{
				try
				{
					var importForm = new ImportDatabaseForm();
					importForm.CurrentDatabase = (this.Model as ModelRoot).Database;
					importForm.ShowDialog();

					switch (importForm.Status)
					{
						case SqlSchemaToModel.ImportReturnConstants.Aborted:
							MessageBox.Show("The import was cancelled.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
							break;
						case SqlSchemaToModel.ImportReturnConstants.NoChange:
							MessageBox.Show("This model is up-to-date. There are no changes to refresh.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
							break;
						case SqlSchemaToModel.ImportReturnConstants.Success:
							MessageBox.Show("The import was completed successfully.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
							break;
					}

				}
				catch (Exception ex)
				{
					throw;
				}
			}
		}

		#endregion

		#region HelperMethods

		public LoadResultConstants ProcessPostModelLoad()
		{
			try
			{
				var root = (ModelRoot)this.RootController.Object;
				if ((root.CompanyName == "[COMPANY NAME]") && root.ProjectName == "[NEW PROJECT]")
				{
					var F = new NewModelWizardForm(root);
					if (F.ShowDialog() == DialogResult.OK)
					{
						if (root.Database.Tables.Count + root.Database.CustomViewColumns.Count + root.Database.CustomStoredProcedures.Count == 0)
						{
							var importForm = new ImportDatabaseForm();
							importForm.ForceAddOnly();
							importForm.CurrentDatabase = root.Database;
							if (importForm.ShowDialog() == DialogResult.OK)
							{
							}
						}

						this.RootController.Object.Dirty = true;
						return LoadResultConstants.SuccessDirty;
					}
					return LoadResultConstants.Success;
				}
				else
				{
					return LoadResultConstants.Success;
				}

			}
			catch (Exception ex)
			{
				return LoadResultConstants.Failed;
			}
		}

		//public static void AddICSharpDllToBinFolder()
		//{
		//  AddAssemblyBinFolder(ICSharpCodeFile);
		//}

		public static void AddWidgetsphereCoreToBinFolder()
		{
			AddAssemblyBinFolder(CoreFile);
		}

		public static void AddWidgetsphereEFCoreToBinFolder()
		{
			AddAssemblyBinFolder(EFCoreFile);
		}

		public static void AddEFCodeFirstToBinFolder()
		{
			AddAssemblyBinFolder(CodeFirstCTP5);
		}

		public static void AddMicrosoftServiceModelWebToBinFolder()
		{
			AddAssemblyBinFolder(MicrosoftServiceModelWeb);
		}

		/// <summary>
		/// Adds the specified assembly from the extensions folder to the generated 'bin' folder
		/// </summary>
		/// <param name="fileName"></param>
		public static void AddAssemblyBinFolder(string fileName)
		{
			var binDirectoryString = Path.Combine(EnvDTEHelper.Instance.SolutionDirectory.FullName, "bin");
			var widgetsphereCoreFileString = Path.Combine(AddinAppData.Instance.ExtensionDirectory, fileName);
			var binDirectory = new DirectoryInfo(binDirectoryString);
			var coreFile = new FileInfo(widgetsphereCoreFileString);
			if (!binDirectory.Exists)
				binDirectory.Create();
			MoveFile(binDirectory, coreFile);
		}

		private static void MoveFile(DirectoryInfo binDirectory, FileInfo fileToMove)
		{
			if (!fileToMove.Exists)
			{
				GlobalHelper.ShowError("Solution will not build because file " + fileToMove.FullName + " could not be moved to " + binDirectory.FullName);
			}
			else
			{
				try
				{
					var movedTo = new FileInfo(Path.Combine(binDirectory.FullName, fileToMove.Name));
					if (!movedTo.Exists)
						fileToMove.CopyTo(movedTo.FullName);
					else
					{
						try
						{
							fileToMove.CopyTo(movedTo.FullName, true);
						}
						catch (Exception ex)
						{
							GlobalHelper.ShowError("Attempt to update file " + fileToMove.FullName + " with the latest from " + binDirectory.FullName + " failed: " + ex.ToString());
						}
					}
				}
				catch (Exception ex)
				{
					GlobalHelper.ShowError("Solution will not build because file " + fileToMove.FullName + " could not be moved to " + binDirectory.FullName + " " + ex.ToString());
				}
			}
		}

		#endregion
	}

}